Из открытых источников доступны исторические данные о продажах игр, оценки пользователей и экспертов, жанры и платформы (например, Xbox или PlayStation). Вам нужно выявить определяющие успешность игры закономерности. Это позволит сделать ставку на потенциально популярный продукт и спланировать рекламные кампании. Перед нами данные до 2016 года.
Описание данных:
Данные за 2016 год могут быть неполными.
Наеобходимо провести работу с данными и определить:
!pip install plotly.express
Requirement already satisfied: plotly.express in c:\programdata\anaconda3\lib\site-packages (0.4.1) Requirement already satisfied: patsy>=0.5 in c:\programdata\anaconda3\lib\site-packages (from plotly.express) (0.5.1) Requirement already satisfied: plotly>=4.1.0 in c:\programdata\anaconda3\lib\site-packages (from plotly.express) (5.3.1) Requirement already satisfied: numpy>=1.11 in c:\programdata\anaconda3\lib\site-packages (from plotly.express) (1.19.2) Requirement already satisfied: scipy>=0.18 in c:\programdata\anaconda3\lib\site-packages (from plotly.express) (1.5.2) Requirement already satisfied: pandas>=0.20.0 in c:\programdata\anaconda3\lib\site-packages (from plotly.express) (1.1.3) Requirement already satisfied: statsmodels>=0.9.0 in c:\programdata\anaconda3\lib\site-packages (from plotly.express) (0.12.0) Requirement already satisfied: six in c:\programdata\anaconda3\lib\site-packages (from patsy>=0.5->plotly.express) (1.15.0) Requirement already satisfied: tenacity>=6.2.0 in c:\programdata\anaconda3\lib\site-packages (from plotly>=4.1.0->plotly.express) (8.0.1) Requirement already satisfied: python-dateutil>=2.7.3 in c:\programdata\anaconda3\lib\site-packages (from pandas>=0.20.0->plotly.express) (2.8.1) Requirement already satisfied: pytz>=2017.2 in c:\programdata\anaconda3\lib\site-packages (from pandas>=0.20.0->plotly.express) (2020.1)
import pandas as pd
import plotly.express as px
from scipy import stats as st
Для начал прочитаем датасет, и проведём ознакомотильный анализ, посмотрим на строки, загаловки и типы данных.
df = pd.read_csv('games.csv')
df.head(15)
| Name | Platform | Year_of_Release | Genre | NA_sales | EU_sales | JP_sales | Other_sales | Critic_Score | User_Score | Rating | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Wii Sports | Wii | 2006.0 | Sports | 41.36 | 28.96 | 3.77 | 8.45 | 76.0 | 8 | E |
| 1 | Super Mario Bros. | NES | 1985.0 | Platform | 29.08 | 3.58 | 6.81 | 0.77 | NaN | NaN | NaN |
| 2 | Mario Kart Wii | Wii | 2008.0 | Racing | 15.68 | 12.76 | 3.79 | 3.29 | 82.0 | 8.3 | E |
| 3 | Wii Sports Resort | Wii | 2009.0 | Sports | 15.61 | 10.93 | 3.28 | 2.95 | 80.0 | 8 | E |
| 4 | Pokemon Red/Pokemon Blue | GB | 1996.0 | Role-Playing | 11.27 | 8.89 | 10.22 | 1.00 | NaN | NaN | NaN |
| 5 | Tetris | GB | 1989.0 | Puzzle | 23.20 | 2.26 | 4.22 | 0.58 | NaN | NaN | NaN |
| 6 | New Super Mario Bros. | DS | 2006.0 | Platform | 11.28 | 9.14 | 6.50 | 2.88 | 89.0 | 8.5 | E |
| 7 | Wii Play | Wii | 2006.0 | Misc | 13.96 | 9.18 | 2.93 | 2.84 | 58.0 | 6.6 | E |
| 8 | New Super Mario Bros. Wii | Wii | 2009.0 | Platform | 14.44 | 6.94 | 4.70 | 2.24 | 87.0 | 8.4 | E |
| 9 | Duck Hunt | NES | 1984.0 | Shooter | 26.93 | 0.63 | 0.28 | 0.47 | NaN | NaN | NaN |
| 10 | Nintendogs | DS | 2005.0 | Simulation | 9.05 | 10.95 | 1.93 | 2.74 | NaN | NaN | NaN |
| 11 | Mario Kart DS | DS | 2005.0 | Racing | 9.71 | 7.47 | 4.13 | 1.90 | 91.0 | 8.6 | E |
| 12 | Pokemon Gold/Pokemon Silver | GB | 1999.0 | Role-Playing | 9.00 | 6.18 | 7.20 | 0.71 | NaN | NaN | NaN |
| 13 | Wii Fit | Wii | 2007.0 | Sports | 8.92 | 8.03 | 3.60 | 2.15 | 80.0 | 7.7 | E |
| 14 | Kinect Adventures! | X360 | 2010.0 | Misc | 15.00 | 4.89 | 0.24 | 1.69 | 61.0 | 6.3 | E |
df.tail(10)
| Name | Platform | Year_of_Release | Genre | NA_sales | EU_sales | JP_sales | Other_sales | Critic_Score | User_Score | Rating | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 16705 | 15 Days | PC | 2009.0 | Adventure | 0.00 | 0.01 | 0.00 | 0.0 | 63.0 | 5.8 | NaN |
| 16706 | Men in Black II: Alien Escape | GC | 2003.0 | Shooter | 0.01 | 0.00 | 0.00 | 0.0 | NaN | tbd | T |
| 16707 | Aiyoku no Eustia | PSV | 2014.0 | Misc | 0.00 | 0.00 | 0.01 | 0.0 | NaN | NaN | NaN |
| 16708 | Woody Woodpecker in Crazy Castle 5 | GBA | 2002.0 | Platform | 0.01 | 0.00 | 0.00 | 0.0 | NaN | NaN | NaN |
| 16709 | SCORE International Baja 1000: The Official Game | PS2 | 2008.0 | Racing | 0.00 | 0.00 | 0.00 | 0.0 | NaN | NaN | NaN |
| 16710 | Samurai Warriors: Sanada Maru | PS3 | 2016.0 | Action | 0.00 | 0.00 | 0.01 | 0.0 | NaN | NaN | NaN |
| 16711 | LMA Manager 2007 | X360 | 2006.0 | Sports | 0.00 | 0.01 | 0.00 | 0.0 | NaN | NaN | NaN |
| 16712 | Haitaka no Psychedelica | PSV | 2016.0 | Adventure | 0.00 | 0.00 | 0.01 | 0.0 | NaN | NaN | NaN |
| 16713 | Spirits & Spells | GBA | 2003.0 | Platform | 0.01 | 0.00 | 0.00 | 0.0 | NaN | NaN | NaN |
| 16714 | Winning Post 8 2016 | PSV | 2016.0 | Simulation | 0.00 | 0.00 | 0.01 | 0.0 | NaN | NaN | NaN |
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 16715 entries, 0 to 16714 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Name 16713 non-null object 1 Platform 16715 non-null object 2 Year_of_Release 16446 non-null float64 3 Genre 16713 non-null object 4 NA_sales 16715 non-null float64 5 EU_sales 16715 non-null float64 6 JP_sales 16715 non-null float64 7 Other_sales 16715 non-null float64 8 Critic_Score 8137 non-null float64 9 User_Score 10014 non-null object 10 Rating 9949 non-null object dtypes: float64(6), object(5) memory usage: 1.4+ MB
df.describe().T
| count | mean | std | min | 25% | 50% | 75% | max | |
|---|---|---|---|---|---|---|---|---|
| Year_of_Release | 16446.0 | 2006.484616 | 5.877050 | 1980.0 | 2003.0 | 2007.00 | 2010.00 | 2016.00 |
| NA_sales | 16715.0 | 0.263377 | 0.813604 | 0.0 | 0.0 | 0.08 | 0.24 | 41.36 |
| EU_sales | 16715.0 | 0.145060 | 0.503339 | 0.0 | 0.0 | 0.02 | 0.11 | 28.96 |
| JP_sales | 16715.0 | 0.077617 | 0.308853 | 0.0 | 0.0 | 0.00 | 0.04 | 10.22 |
| Other_sales | 16715.0 | 0.047342 | 0.186731 | 0.0 | 0.0 | 0.01 | 0.03 | 10.57 |
| Critic_Score | 8137.0 | 68.967679 | 13.938165 | 13.0 | 60.0 | 71.00 | 79.00 | 98.00 |
В данной таблице отражена информация о количество заполнененных строк, и их распределении. Большое количество строк пропущено в в оценке критиков и в даннычх о продажах в каждом регионе. Также много нулевых значений в колонке с продажами.
Прочитали датасет, получили начальную информацию, о содержимом и типах данных. Уже сейчас видны пропуски в каждой колнки, необходимо детальнее изучить пропуски, и принять меры по их заполнению, там где, это возможно, также проверить на другие ошибки.
Первое, что сделаем для удобства работы с данными, приведем заголовки к нижнему регистру.
df.columns = df.columns.str.lower()
df.head()
| name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Wii Sports | Wii | 2006.0 | Sports | 41.36 | 28.96 | 3.77 | 8.45 | 76.0 | 8 | E |
| 1 | Super Mario Bros. | NES | 1985.0 | Platform | 29.08 | 3.58 | 6.81 | 0.77 | NaN | NaN | NaN |
| 2 | Mario Kart Wii | Wii | 2008.0 | Racing | 15.68 | 12.76 | 3.79 | 3.29 | 82.0 | 8.3 | E |
| 3 | Wii Sports Resort | Wii | 2009.0 | Sports | 15.61 | 10.93 | 3.28 | 2.95 | 80.0 | 8 | E |
| 4 | Pokemon Red/Pokemon Blue | GB | 1996.0 | Role-Playing | 11.27 | 8.89 | 10.22 | 1.00 | NaN | NaN | NaN |
Переведём колонки в новые типпы данных, после первичного осмотра данных, начнеи замену с года выпуска, тип данных float переведём в int.
df['year_of_release'].isnull().sum()
269
df.dropna(subset = ['year_of_release'],inplace = True)
df['year_of_release'].isnull().sum()
0
Пропущенных значений с датами мало, допустимо их убрать. После удаления пустых значений, можно год привести к целочисленному числу.
df['year_of_release'] = df['year_of_release'].astype('int')
df.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 16446 entries, 0 to 16714 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 16444 non-null object 1 platform 16446 non-null object 2 year_of_release 16446 non-null int32 3 genre 16444 non-null object 4 na_sales 16446 non-null float64 5 eu_sales 16446 non-null float64 6 jp_sales 16446 non-null float64 7 other_sales 16446 non-null float64 8 critic_score 7983 non-null float64 9 user_score 9839 non-null object 10 rating 9768 non-null object dtypes: float64(5), int32(1), object(5) memory usage: 1.4+ MB
Две игры остались без имени, их тоже еще допустимо удалить.
df.dropna(subset = ['name'],inplace = True)
df['name'].isnull().sum()
df.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 16444 entries, 0 to 16714 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 16444 non-null object 1 platform 16444 non-null object 2 year_of_release 16444 non-null int32 3 genre 16444 non-null object 4 na_sales 16444 non-null float64 5 eu_sales 16444 non-null float64 6 jp_sales 16444 non-null float64 7 other_sales 16444 non-null float64 8 critic_score 7983 non-null float64 9 user_score 9839 non-null object 10 rating 9768 non-null object dtypes: float64(5), int32(1), object(5) memory usage: 1.4+ MB
df.head(22)
| name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Wii Sports | Wii | 2006 | Sports | 41.36 | 28.96 | 3.77 | 8.45 | 76.0 | 8 | E |
| 1 | Super Mario Bros. | NES | 1985 | Platform | 29.08 | 3.58 | 6.81 | 0.77 | NaN | NaN | NaN |
| 2 | Mario Kart Wii | Wii | 2008 | Racing | 15.68 | 12.76 | 3.79 | 3.29 | 82.0 | 8.3 | E |
| 3 | Wii Sports Resort | Wii | 2009 | Sports | 15.61 | 10.93 | 3.28 | 2.95 | 80.0 | 8 | E |
| 4 | Pokemon Red/Pokemon Blue | GB | 1996 | Role-Playing | 11.27 | 8.89 | 10.22 | 1.00 | NaN | NaN | NaN |
| 5 | Tetris | GB | 1989 | Puzzle | 23.20 | 2.26 | 4.22 | 0.58 | NaN | NaN | NaN |
| 6 | New Super Mario Bros. | DS | 2006 | Platform | 11.28 | 9.14 | 6.50 | 2.88 | 89.0 | 8.5 | E |
| 7 | Wii Play | Wii | 2006 | Misc | 13.96 | 9.18 | 2.93 | 2.84 | 58.0 | 6.6 | E |
| 8 | New Super Mario Bros. Wii | Wii | 2009 | Platform | 14.44 | 6.94 | 4.70 | 2.24 | 87.0 | 8.4 | E |
| 9 | Duck Hunt | NES | 1984 | Shooter | 26.93 | 0.63 | 0.28 | 0.47 | NaN | NaN | NaN |
| 10 | Nintendogs | DS | 2005 | Simulation | 9.05 | 10.95 | 1.93 | 2.74 | NaN | NaN | NaN |
| 11 | Mario Kart DS | DS | 2005 | Racing | 9.71 | 7.47 | 4.13 | 1.90 | 91.0 | 8.6 | E |
| 12 | Pokemon Gold/Pokemon Silver | GB | 1999 | Role-Playing | 9.00 | 6.18 | 7.20 | 0.71 | NaN | NaN | NaN |
| 13 | Wii Fit | Wii | 2007 | Sports | 8.92 | 8.03 | 3.60 | 2.15 | 80.0 | 7.7 | E |
| 14 | Kinect Adventures! | X360 | 2010 | Misc | 15.00 | 4.89 | 0.24 | 1.69 | 61.0 | 6.3 | E |
| 15 | Wii Fit Plus | Wii | 2009 | Sports | 9.01 | 8.49 | 2.53 | 1.77 | 80.0 | 7.4 | E |
| 16 | Grand Theft Auto V | PS3 | 2013 | Action | 7.02 | 9.09 | 0.98 | 3.96 | 97.0 | 8.2 | M |
| 17 | Grand Theft Auto: San Andreas | PS2 | 2004 | Action | 9.43 | 0.40 | 0.41 | 10.57 | 95.0 | 9 | M |
| 18 | Super Mario World | SNES | 1990 | Platform | 12.78 | 3.75 | 3.54 | 0.55 | NaN | NaN | NaN |
| 19 | Brain Age: Train Your Brain in Minutes a Day | DS | 2005 | Misc | 4.74 | 9.20 | 4.16 | 2.04 | 77.0 | 7.9 | E |
| 20 | Pokemon Diamond/Pokemon Pearl | DS | 2006 | Role-Playing | 6.38 | 4.46 | 6.04 | 1.36 | NaN | NaN | NaN |
| 21 | Super Mario Land | GB | 1989 | Platform | 10.83 | 2.71 | 4.18 | 0.42 | NaN | NaN | NaN |
df['rating'].value_counts()
E 3921 T 2905 M 1536 E10+ 1393 EC 8 K-A 3 RP 1 AO 1 Name: rating, dtype: int64
В колонке с рейтингом, есть пропуски , которые скорее всего они не были проанализированы. Заполнить такое количество пропусков одним значением будет ошибочно.
Пропуски в полонке с пользовательской оценкой могли появится, потому что оценки нет, поэтому заменим их и значения tbd нулями.
df['user_score'] = df['user_score'].fillna(0)
df[df['user_score']==0].tail()
| name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 16710 | Samurai Warriors: Sanada Maru | PS3 | 2016 | Action | 0.00 | 0.00 | 0.01 | 0.0 | NaN | 0 | NaN |
| 16711 | LMA Manager 2007 | X360 | 2006 | Sports | 0.00 | 0.01 | 0.00 | 0.0 | NaN | 0 | NaN |
| 16712 | Haitaka no Psychedelica | PSV | 2016 | Adventure | 0.00 | 0.00 | 0.01 | 0.0 | NaN | 0 | NaN |
| 16713 | Spirits & Spells | GBA | 2003 | Platform | 0.01 | 0.00 | 0.00 | 0.0 | NaN | 0 | NaN |
| 16714 | Winning Post 8 2016 | PSV | 2016 | Simulation | 0.00 | 0.00 | 0.01 | 0.0 | NaN | 0 | NaN |
df['user_score'].value_counts()
0 6605
tbd 2376
7.8 322
8 285
8.2 276
...
1.5 2
1.1 2
1.3 2
9.7 1
0 1
Name: user_score, Length: 97, dtype: int64
df['user_score'] = df['user_score'].replace('tbd',0)
df['user_score'].value_counts()
0 8981
7.8 322
8 285
8.2 276
8.3 252
...
1.1 2
0.3 2
0.7 2
0 1
9.7 1
Name: user_score, Length: 96, dtype: int64
Видна зависимость между оценкой критиков и пользователей, другую зависмость со значением колонки оценка критиков найти не удается, поэтому заменим пропуски также нулями, скорее всего оценка не известна.
df['critic_score'] = df ['critic_score'].fillna(0)
df.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 16444 entries, 0 to 16714 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 16444 non-null object 1 platform 16444 non-null object 2 year_of_release 16444 non-null int32 3 genre 16444 non-null object 4 na_sales 16444 non-null float64 5 eu_sales 16444 non-null float64 6 jp_sales 16444 non-null float64 7 other_sales 16444 non-null float64 8 critic_score 16444 non-null float64 9 user_score 16444 non-null object 10 rating 9768 non-null object dtypes: float64(5), int32(1), object(5) memory usage: 1.4+ MB
Добавим новый столбец с суммой продаж во всех регионах.
df['sum_sale'] = df['na_sales'] + df['eu_sales'] + df['jp_sales'] + df['other_sales']
df.head()
| name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | sum_sale | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Wii Sports | Wii | 2006 | Sports | 41.36 | 28.96 | 3.77 | 8.45 | 76.0 | 8 | E | 82.54 |
| 1 | Super Mario Bros. | NES | 1985 | Platform | 29.08 | 3.58 | 6.81 | 0.77 | 0.0 | 0 | NaN | 40.24 |
| 2 | Mario Kart Wii | Wii | 2008 | Racing | 15.68 | 12.76 | 3.79 | 3.29 | 82.0 | 8.3 | E | 35.52 |
| 3 | Wii Sports Resort | Wii | 2009 | Sports | 15.61 | 10.93 | 3.28 | 2.95 | 80.0 | 8 | E | 32.77 |
| 4 | Pokemon Red/Pokemon Blue | GB | 1996 | Role-Playing | 11.27 | 8.89 | 10.22 | 1.00 | 0.0 | 0 | NaN | 31.38 |
df['user_score'] = df['user_score'].astype('float')
df.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 16444 entries, 0 to 16714 Data columns (total 12 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 16444 non-null object 1 platform 16444 non-null object 2 year_of_release 16444 non-null int32 3 genre 16444 non-null object 4 na_sales 16444 non-null float64 5 eu_sales 16444 non-null float64 6 jp_sales 16444 non-null float64 7 other_sales 16444 non-null float64 8 critic_score 16444 non-null float64 9 user_score 16444 non-null float64 10 rating 9768 non-null object 11 sum_sale 16444 non-null float64 dtypes: float64(7), int32(1), object(4) memory usage: 1.6+ MB
print(df.duplicated().sum())
0
Привели заголовку к удобному виду, заменили тип данных, где это было необходимо, проработали пропуски. Не все пропуски возможно заполнить на основе данных датасета, поэтому заполнили некоторые нулями, чтобы было удобно совершать арифметические опперации, и какие-то пропуски оставили в датасете.
display(df.groupby('year_of_release')['name'].count())
year_of_release 1980 9 1981 46 1982 36 1983 17 1984 14 1985 14 1986 21 1987 16 1988 15 1989 17 1990 16 1991 41 1992 43 1993 60 1994 121 1995 219 1996 263 1997 289 1998 379 1999 338 2000 350 2001 482 2002 829 2003 775 2004 762 2005 939 2006 1006 2007 1197 2008 1427 2009 1426 2010 1255 2011 1136 2012 653 2013 544 2014 581 2015 606 2016 502 Name: name, dtype: int64
for years in sorted(df['year_of_release'].unique()):
fig = px.bar(df.query('year_of_release == @years').pivot_table(index = 'platform',
values = 'sum_sale', aggfunc = sum).reset_index(),
x = 'platform',y = 'sum_sale', color = 'platform',title = str(years),template = 'plotly_dark')
fig.show()
Примерно 5 лет выделим в актуальный промежуток времени, примерно в столько лет происходит смена платформы.Как правило плафтормы лидеры не сохраняются на протяжении нескольких лет.
df_actual = df.query('year_of_release >=2011')
df_actual_platform = df_actual.groupby(['platform','year_of_release'])['sum_sale'].sum().reset_index()
df_actual_platform
| platform | year_of_release | sum_sale | |
|---|---|---|---|
| 0 | 3DS | 2011 | 63.20 |
| 1 | 3DS | 2012 | 51.36 |
| 2 | 3DS | 2013 | 56.57 |
| 3 | 3DS | 2014 | 43.76 |
| 4 | 3DS | 2015 | 27.78 |
| 5 | 3DS | 2016 | 15.14 |
| 6 | DS | 2011 | 26.18 |
| 7 | DS | 2012 | 11.01 |
| 8 | DS | 2013 | 1.54 |
| 9 | PC | 2011 | 35.03 |
| 10 | PC | 2012 | 23.22 |
| 11 | PC | 2013 | 12.38 |
| 12 | PC | 2014 | 13.28 |
| 13 | PC | 2015 | 8.52 |
| 14 | PC | 2016 | 5.25 |
| 15 | PS2 | 2011 | 0.45 |
| 16 | PS3 | 2011 | 156.78 |
| 17 | PS3 | 2012 | 107.36 |
| 18 | PS3 | 2013 | 113.25 |
| 19 | PS3 | 2014 | 47.76 |
| 20 | PS3 | 2015 | 16.82 |
| 21 | PS3 | 2016 | 3.60 |
| 22 | PS4 | 2013 | 25.99 |
| 23 | PS4 | 2014 | 100.00 |
| 24 | PS4 | 2015 | 118.90 |
| 25 | PS4 | 2016 | 69.25 |
| 26 | PSP | 2011 | 17.82 |
| 27 | PSP | 2012 | 7.69 |
| 28 | PSP | 2013 | 3.14 |
| 29 | PSP | 2014 | 0.24 |
| 30 | PSP | 2015 | 0.12 |
| 31 | PSV | 2011 | 4.63 |
| 32 | PSV | 2012 | 16.19 |
| 33 | PSV | 2013 | 10.59 |
| 34 | PSV | 2014 | 11.90 |
| 35 | PSV | 2015 | 6.25 |
| 36 | PSV | 2016 | 4.25 |
| 37 | Wii | 2011 | 59.65 |
| 38 | Wii | 2012 | 21.71 |
| 39 | Wii | 2013 | 8.59 |
| 40 | Wii | 2014 | 3.75 |
| 41 | Wii | 2015 | 1.14 |
| 42 | Wii | 2016 | 0.18 |
| 43 | WiiU | 2012 | 17.56 |
| 44 | WiiU | 2013 | 21.65 |
| 45 | WiiU | 2014 | 22.03 |
| 46 | WiiU | 2015 | 16.35 |
| 47 | WiiU | 2016 | 4.60 |
| 48 | X360 | 2011 | 143.84 |
| 49 | X360 | 2012 | 99.74 |
| 50 | X360 | 2013 | 88.58 |
| 51 | X360 | 2014 | 34.74 |
| 52 | X360 | 2015 | 11.96 |
| 53 | X360 | 2016 | 1.52 |
| 54 | XOne | 2013 | 18.96 |
| 55 | XOne | 2014 | 54.07 |
| 56 | XOne | 2015 | 60.14 |
| 57 | XOne | 2016 | 26.15 |
for platform in sorted(df_actual_platform['platform'].unique()):
fig = px.bar(df_actual_platform.query('platform == @platform'), x = 'year_of_release',y = 'sum_sale',
title = platform, template = 'plotly_dark')
fig.show()
Популярность любой платформы, с годами падает, в редких случаев сначала возрастает, но в итоге все равно падает.
df_actual.groupby('platform')['sum_sale'].sum().sort_values(ascending=False).head(3)
platform PS3 445.57 X360 380.38 PS4 314.14 Name: sum_sale, dtype: float64
Были обнаружены лидеры игоровых платформ за последнии 5 лет.
fig = px.box(df_actual_platform, x = 'platform',y = 'sum_sale', template = 'plotly_dark')
fig.show()
Мы видим, что значения глобальных продаж у платформ почти не имеет выбросов. Теперь возьмем данные за актуальный период по самой популярной платформе PS 3.
df_ps3 = df[(df['platform']=='PS3') & (df['year_of_release']>=2011)]
df_ps3
| name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | sum_sale | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 16 | Grand Theft Auto V | PS3 | 2013 | Action | 7.02 | 9.09 | 0.98 | 3.96 | 97.0 | 8.2 | M | 21.05 |
| 34 | Call of Duty: Black Ops II | PS3 | 2012 | Shooter | 4.99 | 5.73 | 0.65 | 2.42 | 83.0 | 5.3 | M | 13.79 |
| 37 | Call of Duty: Modern Warfare 3 | PS3 | 2011 | Shooter | 5.54 | 5.73 | 0.49 | 1.57 | 88.0 | 3.2 | M | 13.33 |
| 69 | Call of Duty: Ghosts | PS3 | 2013 | Shooter | 4.10 | 3.63 | 0.38 | 1.25 | 71.0 | 2.6 | M | 9.36 |
| 81 | FIFA Soccer 13 | PS3 | 2012 | Action | 1.06 | 5.01 | 0.13 | 1.97 | 88.0 | 6.6 | E | 8.17 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 16628 | Akatsuki no Goei Trinity | PS3 | 2012 | Adventure | 0.00 | 0.00 | 0.01 | 0.00 | 0.0 | 0.0 | NaN | 0.01 |
| 16638 | Tour de France 2014 | PS3 | 2014 | Sports | 0.00 | 0.01 | 0.00 | 0.00 | 0.0 | 0.0 | E | 0.01 |
| 16674 | Tsukigime Ranko's Longest Day | PS3 | 2014 | Action | 0.00 | 0.01 | 0.00 | 0.00 | 0.0 | 0.0 | NaN | 0.01 |
| 16691 | Dynasty Warriors: Eiketsuden | PS3 | 2016 | Action | 0.00 | 0.00 | 0.01 | 0.00 | 0.0 | 0.0 | NaN | 0.01 |
| 16710 | Samurai Warriors: Sanada Maru | PS3 | 2016 | Action | 0.00 | 0.00 | 0.01 | 0.00 | 0.0 | 0.0 | NaN | 0.01 |
708 rows × 12 columns
df_ps3.corr()
| year_of_release | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | sum_sale | |
|---|---|---|---|---|---|---|---|---|
| year_of_release | 1.000000 | -0.151349 | -0.096637 | -0.058354 | -0.103186 | -0.398094 | -0.222644 | -0.123980 |
| na_sales | -0.151349 | 1.000000 | 0.837404 | 0.336445 | 0.875382 | 0.360210 | 0.255010 | 0.937887 |
| eu_sales | -0.096637 | 0.837404 | 1.000000 | 0.357487 | 0.979257 | 0.271789 | 0.186047 | 0.968964 |
| jp_sales | -0.058354 | 0.336445 | 0.357487 | 1.000000 | 0.362607 | 0.167173 | 0.155719 | 0.438093 |
| other_sales | -0.103186 | 0.875382 | 0.979257 | 0.362607 | 1.000000 | 0.291919 | 0.206101 | 0.978086 |
| critic_score | -0.398094 | 0.360210 | 0.271789 | 0.167173 | 0.291919 | 1.000000 | 0.791748 | 0.324330 |
| user_score | -0.222644 | 0.255010 | 0.186047 | 0.155719 | 0.206101 | 0.791748 | 1.000000 | 0.229875 |
| sum_sale | -0.123980 | 0.937887 | 0.968964 | 0.438093 | 0.978086 | 0.324330 | 0.229875 | 1.000000 |
fig = px.scatter(df_actual, x = 'sum_sale', y = 'user_score', color = 'platform',
title = 'Корреляция цены в зав-ти от оценки пользователя по платформам', template = 'plotly_dark')
fig.show()
Можно сделать вывод, что продажи слабо зависят от оценки пользователей и критиков, вне зависимости от платформы о которой идет речь.
df_actual['genre'].unique()
array(['Action', 'Shooter', 'Role-Playing', 'Racing', 'Platform', 'Misc',
'Simulation', 'Sports', 'Fighting', 'Adventure', 'Puzzle',
'Strategy'], dtype=object)
fig = px.line(df_actual.pivot_table(index = ['genre','year_of_release'], values = 'sum_sale',aggfunc = 'sum').reset_index(),
x = 'year_of_release', y = 'sum_sale',color = 'genre',title = 'Продажи разных жанров',template = 'plotly_dark')
fig.show()
Посмотрев продажи игр за актуальный период, можно наблюдать спад продаж игр всех жанров, однако самый продаваемы жанр Action, а самый менее продаваемый Puzzle.
df_region = df_actual.pivot_table(index = 'platform',values = ['na_sales','eu_sales','jp_sales'],aggfunc = 'sum').reset_index()
df_na = df_region.loc[:,['platform','na_sales']]
df_na.sort_values('na_sales',ascending = False).head()
| platform | na_sales | |
|---|---|---|
| 10 | X360 | 226.80 |
| 4 | PS3 | 168.26 |
| 5 | PS4 | 108.74 |
| 11 | XOne | 93.12 |
| 0 | 3DS | 82.65 |
df_eu = df_region.loc[:,['platform','eu_sales']]
df_eu.sort_values('eu_sales',ascending = False).head()
| platform | eu_sales | |
|---|---|---|
| 4 | PS3 | 163.10 |
| 5 | PS4 | 141.09 |
| 10 | X360 | 117.10 |
| 0 | 3DS | 61.27 |
| 2 | PC | 56.70 |
df_jp = df_region.loc[:,['platform','jp_sales']]
df_jp.sort_values('jp_sales',ascending = False).head()
| platform | jp_sales | |
|---|---|---|
| 0 | 3DS | 100.62 |
| 4 | PS3 | 49.39 |
| 6 | PSP | 24.04 |
| 7 | PSV | 21.84 |
| 5 | PS4 | 15.96 |
В зависимотси от региона топ 5 платформ по продажам разные.
df_region_genre = df_actual.pivot_table(index = 'genre',values = ['na_sales','eu_sales','jp_sales'],aggfunc = 'sum').reset_index()
df_na_genre = df_region_genre.loc[:,['genre','na_sales']]
df_na_genre.sort_values('na_sales',ascending = False).head()
| genre | na_sales | |
|---|---|---|
| 0 | Action | 230.92 |
| 8 | Shooter | 194.43 |
| 10 | Sports | 108.70 |
| 7 | Role-Playing | 83.78 |
| 3 | Misc | 69.69 |
df_eu_genre = df_region_genre.loc[:,['genre','eu_sales']]
df_eu_genre.sort_values('eu_sales',ascending = False).head()
| genre | eu_sales | |
|---|---|---|
| 0 | Action | 199.12 |
| 8 | Shooter | 148.02 |
| 10 | Sports | 88.48 |
| 7 | Role-Playing | 62.30 |
| 6 | Racing | 40.58 |
df_jp_genre = df_region_genre.loc[:,['genre','jp_sales']]
df_jp_genre.sort_values('jp_sales',ascending = False).head()
| genre | jp_sales | |
|---|---|---|
| 7 | Role-Playing | 79.87 |
| 0 | Action | 63.62 |
| 3 | Misc | 17.60 |
| 2 | Fighting | 12.38 |
| 4 | Platform | 12.13 |
По жанрам в Северной Америке и Европе топ жанров одинаковый, а в Японии популярный другие жанры.
Сначала проверим гипотезу : средние пользовательские рейтинги платформ Xbox One и PC одинаковые. Сформулируем нулевую(H0) и альтернативную гипотезу(H1):
alpha = 0.05
results = st.ttest_ind(df_actual.query('platform == "XOne"')['user_score'], df_actual.query('platform == "PC"')['user_score'])
print('p-значение:', results.pvalue)
if results.pvalue < alpha:
print('Отвергаем нулевую гипотезу')
else:
print('Не получилось отвергнуть нулевую гипотезу')
p-значение: 0.24758279963021285 Не получилось отвергнуть нулевую гипотезу
Рейтинги пользователей двух платформ равны.
Средние пользовательские рейтинги жанров Action (англ. «действие», экшен-игры) и Sports (англ. «спортивные соревнования») разные.
alpha = 0.05
results = st.ttest_ind(df_actual.query('genre == "Action"')['user_score'], df_actual.query('genre == "Sports"')['user_score'])
print('p-значение:', results.pvalue)
if results.pvalue < alpha:
print('Отвергаем нулевую гипотезу')
else:
print('Не получилось отвергнуть нулевую гипотезу')
p-значение: 0.8873490835057937 Не получилось отвергнуть нулевую гипотезу
Проверив второе предположение делаем вывод, что рейтинги двух представленных жанров разные.
В ходе работы с данным датасетом установили:
Для того, чтобы сделать все эти вывовды было необходимо: провести ознакомительный осмотр данных, найти ошибки в типах данных и пропуски, навести порядок в датасете, установить верный тип данных, заменить пропуски(по возможности),проверить на дубликаты, провести исследовательский анализ, понять что происходит с жанрами и платформами с течением времени, проверить предполоэения, проведя статистический анлиз.